# _*_ coding:utf-8 _*_
# at:2023-11-22
# author:zizle
import datetime
import pandas as pd
from utils import split_number_en
from iFinDPy import THS_iFinDLogin, THS_iFinDLogout, THS_DP, THS_HQ, THS_BD, THS_EDBQuery

__all__ = ['THSClientAPI']


class THSClientAPI:
    def __enter__(self):
        ret = THS_iFinDLogin('rdqh085', 'rdrj180912')
        assert ret == 0
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        THS_iFinDLogout()

    def get_futures_contract(self, run_date: datetime.date):
        q_date = run_date.strftime('%Y-%m-%d')
        # 数据池-板块_板块成分-日期;同花顺代码-iFinD数据接口（境内在交易合约）
        all_contract = THS_DP('block', f'{q_date};091013;monthcontract', 'date:Y,thscode:Y')
        if all_contract.errorcode != 0:
            raise ValueError('获取境内在交易合约失败!{}'.format(all_contract.errorcode))

        # 数据池-板块_板块成分-日期;同花顺代码-iFinD数据接口（国内主力合约）security_name:Y
        main_contract = THS_DP('block', f'{q_date};091012001;monthcontract', 'date:Y,thscode:Y')
        if main_contract.errorcode != 0:
            raise ValueError('获取主力合约失败!{}'.format(all_contract.errorcode))

        all_contracts = all_contract.data.to_dict(orient='records')
        main_contracts = [mc['THSCODE'] for mc in main_contract.data.to_dict(orient='records')]
        today_contracts = []
        for ac in all_contracts:
            contract = ac['THSCODE'].split('.')[0]  # 合约代码
            # 分离合约和代码
            v, c = split_number_en(contract)
            c_item = {
                'contract_date': ac['DATE'].replace('/', '-'),
                'variety_en': v.upper(),
                'ex_code': ac['THSCODE'],
                'lcontract': f'{q_date[2]}{c}' if len(c) < 4 else c,
                'scontract': c,
                'activity': 0 if ac['THSCODE'] in main_contracts else 1
            }
            today_contracts.append(c_item)
        today_contracts.sort(key=lambda x: x['ex_code'])
        return today_contracts

    def get_history_quote(self, index_item, close_date: str = None):
        start_date = index_item['enddate'] if index_item['enddate'] else index_item['startdate']
        close_date = close_date if close_date else datetime.date.today().strftime('%Y-%m-%d')
        # 历史行情-期货-收盘价;结算价-iFinD数据接口(codes, indicators, parameters, dataformat)
        ret = THS_HQ(index_item['ths_code'], index_item['ths_indicate'], '', start_date, close_date)
        if ret.errorcode != 0:
            print(
                f'\033[1;34m获取 {index_item["source_id"]} 数据, 起始日期:{start_date}.失败了，code={ret.errorcode} {ret.errmsg} \033[0m')
            return []
        index_data = ret.data[['time', index_item['ths_indicate']]]
        # print(index_data)
        ret_df = index_data.rename(columns={'time': 'datadate', index_item['ths_indicate']: 'datavalue'})
        # 检验date格式
        ret_df['datadate'] = ret_df['datadate'].apply(lambda x: datetime.datetime.strptime(x, '%Y-%m-%d').strftime('%Y-%m-%d'))
        ret_df['datavalue'] = pd.to_numeric(ret_df['datavalue'])
        ret_df['datavalue'] = ret_df['datavalue'].astype(float)
        ret_df.fillna(0, inplace=True)
        return ret_df.to_dict(orient='records')

    def get_implied_volatility(self, op_code, run_date: datetime.date):
        ret = THS_BD(op_code, 'ths_implied_volatility_option', run_date.strftime('%Y-%m-%d'))  # 期权隐含波动率
        value = ret.data.iloc[0]['ths_implied_volatility_option']
        return round(value * 100, 2) if value is not None else value

    def get_history_volatility(self, op_code, run_date: datetime.date, day_count: int):
        # 基础数据-期权-标的历史波动率-iFinD数据接口
        q_date = run_date.strftime('%Y-%m-%d')
        ret = THS_BD(op_code, 'ths_anal_volatility_underlying_option', f'{q_date},{day_count},252')
        value = ret.data.iloc[0]['ths_anal_volatility_underlying_option']
        return round(value, 4) if value is not None else value

    def get_edb(self, source_id, start, end):
        ret = THS_EDBQuery(source_id, start, end)
        if not ret:
            return None

        if ret['errorcode'] != 0:
            print(f'\033[1;34m获取 {source_id} 数据, 起始日期:{start}.失败了，code={ret["errorcode"]} \033[0m')
            print(ret['errmsg'])
            return None
        index_data = ret['tables'][0]
        date_list = index_data['time']
        value_list = index_data['value']
        if not date_list or not value_list:
            print(f'获取{source_id},起始:{start}数据为空!')
            return None
        # 整理保存数据
        return list(zip(date_list, value_list))


